垃圾收集算法
可作为GC Roots的对象包括:
- 虚拟机栈(栈帧中的本地变量表)中的引用对象
- 方法区中的类静态属性引用的对象
- 方法区中的常量引用的对象
- 本地方法栈中JNI的引用对象
标记-清除算法
其缺点为:
- 效率不高
- 标记清除之后会产生大量不连续的内存碎片
复制算法
它将可用内存容量划分为大小相等的两块,每次只使用其中的一块,当这一块用完之后,就将还存活的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉,这样使得每次都是对其中一块内存进行回收,不会产生碎片等情况。其缺点是内存缩小为原来的一半。
标记-清理算法
其缺点为在标记-清除的基础上还需进行对象的移动,成本相对较高,好处就是不会产生内存碎片。
垃圾收集器
如上图所示,有7种收集器,分为两块,上面为新生代收集器,下面为老年代收集器,如果两个收集器之间存在连线,就说明它们可以搭配使用。
Serial(串行GC)收集器
其为一个新生代的收集器,单线程执行,使用复制算法,它在进行垃圾回收的时候,必须暂停其他所有的工作线程(用户线程),对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程手机效率。
ParNew(并行)收集器
ParNew收集器就是Serial收集器的多线程版本。
Parallel Scavenge(并行回收GC)收集器
Parallel Scavenge收集器也是一个新生代收集器,它也是使用复制算法的收集器,又是并行多线程收集器, Parallel Scavenge收集器的特点是它的关注点与其他收集器不同,CMS等收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量,吞吐量 = 程序运行时间 / (程序运行时间 + 垃圾收集时间)。
Serial Old(串行GC)收集器
其为Serial收集器的老年代版本,它同样使用一个单线程执行收集,使用“标记-整理”算法。
Parallel Old(并行GC)收集器
Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。
CMS(并发GC)收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,CMS收集器是基于“标记-清除”算法实现的,整个收集过程分为4个步骤:
- 初始标记
- 并发标记
- 重新标记
- 并发清除
其中初始标记、重新标记这两个步骤任然需要停顿其他用户线程。初始标记仅仅只是标记出GC ROOTS能直接关联到的对象,速度很快,并发标记阶段是进行GC ROOTS 根搜索算法阶段,会判定对象是否存活。而重新标记阶段则是为了修正并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间会被初始标记阶段稍长,但比并发标记 阶段要短。
由于整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,所以整体来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。
CMS收集器的优点:并发收集、低停顿,但是CMS还远远达不到完美,器主要有三个显著缺点:
CMS收集器对CPU资源非常敏感。在并发阶段,虽然不会导致用户线程停顿,但是会占用CPU资源而导致引用程序变慢,总吞吐量下降。CMS默认启动的回收线程数是:(CPU数量+3) / 4。
G1收集器
G1(Garbage First)收集器是JDK1.7提供的一个新收集器,G1收集器基于“标记-整理”算法实现,不会产生内存碎片,还有一个特点就是G1将整个Java堆(包括新生代和老年代)。
说明
本文转载自Java虚拟机学习 - 垃圾收集器 (4)。